#include <stdio.h>
#include <stdlib.h>
#include <glib.h>

/**
 * Applique une expression régulière à une chaîne de caractères.
 * @param expr : l'expression régulière au format compatible perl
 * @param chaine : la chaine sur laquel appliquer l'expression
 * @return les différentes partie de la chaine sellectionnées par l'expression s'il l'expression ne correspond pas à la chaine, le résultat est NULL
 */
gchar **
recup_match_chaine(const gchar *expr, const gchar *chaine) {
  int nb_chaines_capturees = 0;
  gchar **result = NULL;
  GMatchInfo *match_info = NULL;

  GError *err = NULL;
  GRegex *reg = g_regex_new(expr, 0, 0, &err);
  if (reg == NULL) { // si l'expression n'est pas correcte
    fprintf(stderr, "ERR : La chaine %s n'est pas une expression régulière correcte car : %s\n", expr, (err)->message);
    return NULL;
  }

  if (g_regex_match(reg, chaine, 0, &match_info)) {
    int i;

    // on compte le nombre de captures recherchées et trouvées dans la chaine
    nb_chaines_capturees = g_regex_get_capture_count(reg);
    fprintf(stderr, "%d chaines capturées\n",  nb_chaines_capturees);

    // on reserve de la place pour stocker les chaines trouvées
    result = g_malloc0((nb_chaines_capturees+1)*sizeof(char*));

    // on lit les valeurs trouvées
    // attention, les chaines trouvées sont de 1 à nb_chaines_capturees
    for (i=1; i<=nb_chaines_capturees; i++) {
      gchar *word = g_match_info_fetch (match_info, i);
      result[i-1] = word;
    }
    // on ajoute NULL dans la dernière case pour signaler la fin de la liste
    result[nb_chaines_capturees] = NULL;
  } else {   
    fprintf(stderr, "la chaine %s ne correspond pas à l'expression %s\n", chaine, expr);
    result = NULL;
  }
  
  g_match_info_free(match_info);
  g_regex_unref(reg);

  return result;
}


int main(int argc, char* argv[]) {
  int i;
  gchar **matchs = NULL;
  if (argc != 3) {
    fprintf(stderr, "usage %s \"<expression>\" \"<chaine à tester>\"\n", argv[0]);
    exit(1);
  }

  matchs = recup_match_chaine(argv[1], argv[2]);
  if (matchs == NULL) {
    fprintf(stderr, "la chaine %s ne correspond pas à l'expression %s\n", argv[1], argv[0]);
  } else {

    i = 0;
    fprintf(stderr, "Les chaines trouvées sont :\n");
    while (matchs[i] != NULL) {
      // affichage de la chaine
      fprintf(stdout, "  %s\n", matchs[i]);
      // on en profite pour libérer la place mémoire
      g_free(matchs[i]);
      i++;
    }
    g_free(matchs);
  }

  return 0;
}
